package tracetest

import (
	"context"
	"fmt"
	"gfweb/tracing"
	"github.com/gogf/gcache-adapter/adapter"
	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/net/gtrace"
	"time"
)

var Tracetest2 = new(tracetestApi2)

type tracetestApi2 struct {
}
type userApiInsert struct {
	Name string `v:"required#Please input user name."`
}

func (p *tracetestApi2) Test1() {
	flush, err := tracing.InitJaeger(ServiceName, JaegerUdpEndpoint)
	if err != nil {
		g.Log().Fatal(err)
	}
	defer flush()

	g.DB().GetCache().SetAdapter(adapter.NewRedis(g.Redis()))
	//g.DB().GetCache().SetAdapter(adapter.NewRedis(gredis.Instance("test")))
	s := g.Server()
	s.Group("/", func(group *ghttp.RouterGroup) {
		group.Middleware(ghttp.MiddlewareServerTracing)
		group.ALL("/user", new(tracetestApi2))
	})
	//s.SetPort(8199)
	s.Run()
}

func (p *tracetestApi2) Test2() {
	flush, err := tracing.InitJaeger(ServiceName, JaegerUdpEndpoint)
	if err != nil {
		g.Log().Fatal(err)
	}
	defer flush()

	p.StartRequests()
}

// Insert is a route handler for inserting user info into dtabase.
func (api *tracetestApi2) Insert(r *ghttp.Request) {
	var (
		dataReq *userApiInsert
	)
	if err := r.Parse(&dataReq); err != nil {
		r.Response.WriteExit(gerror.Current(err))
	}
	result, err := g.Table("user").Ctx(r.Context()).Insert(g.Map{
		"name": dataReq.Name,
	})
	if err != nil {
		r.Response.WriteExit(gerror.Current(err))
	}
	id, _ := result.LastInsertId()
	r.Response.Write(id)
}

type userApiQuery struct {
	Id int `v:"min:1#User id is required for querying."`
}

// Query is a route handler for querying user info. It firstly retrieves the info from redis,
// if there's nothing in the redis, it then does db select.
func (api *tracetestApi2) Query(r *ghttp.Request) {
	var (
		dataReq *userApiQuery
	)
	if err := r.Parse(&dataReq); err != nil {
		r.Response.WriteExit(gerror.Current(err))
	}
	one, err := g.Table("user").
		Ctx(r.Context()).
		Cache(5*time.Second, api.userCacheKey(dataReq.Id)).
		FindOne(dataReq.Id)
	if err != nil {
		r.Response.WriteExit(gerror.Current(err))
	}
	r.Response.WriteJson(one)
}

type userApiDelete struct {
	Id int `v:"min:1#User id is required for deleting."`
}

// Delete is a route handler for deleting specified user info.
func (api *tracetestApi2) Delete(r *ghttp.Request) {
	var (
		dataReq *userApiDelete
	)
	if err := r.Parse(&dataReq); err != nil {
		r.Response.WriteExit(gerror.Current(err))
	}
	_, err := g.Table("user").
		Ctx(r.Context()).
		Cache(-1, api.userCacheKey(dataReq.Id)).
		WherePri(dataReq.Id).
		Delete()
	if err != nil {
		r.Response.WriteExit(gerror.Current(err))
	}
	r.Response.Write("ok")
}

func (api *tracetestApi2) userCacheKey(id int) string {
	return fmt.Sprintf(`userInfo:%d`, id)
}

func (api *tracetestApi2) StartRequests() {
	ctx, span := gtrace.NewSpan(context.Background(), "StartRequests")
	defer span.End()

	client := g.Client().Use(ghttp.MiddlewareClientTracing)
	// Add user info.
	idStr := client.Ctx(ctx).PostContent(
		"http://127.0.0.1:8199/user/insert",
		g.Map{
			"name": "john",
		},
	)
	if idStr == "" {
		g.Log().Ctx(ctx).Print("retrieve empty id string")
		return
	}
	g.Log().Ctx(ctx).Print("insert:", idStr)

	// Query user info.
	userJson := client.Ctx(ctx).GetContent(
		"http://127.0.0.1:8199/user/query",
		g.Map{
			"id": idStr,
		},
	)
	g.Log().Ctx(ctx).Print("query:", idStr, userJson)

	// Delete user info.
	deleteResult := client.Ctx(ctx).PostContent(
		"http://127.0.0.1:8199/user/delete",
		g.Map{
			"id": idStr,
		},
	)
	g.Log().Ctx(ctx).Print("delete:", idStr, deleteResult)
}
